2016-05-08 12:56:18 testcs_dn 阅读数 6589
  • Ceph 介绍

    能够快速部署 Ceph 分布式存储 部署及维护Ceph 的块存储,对象存储,文件系统存储 Ceph 基础知识的理解以及监控

    24682课时 0分钟 697人学习 臧雪园
    免费试看

这里只是演示如何在ubuntu下编译运行Swift开发的Web后端项目。

项目代码来自Bluemix上提供的示例代码,如果你有账号,可以去自己的空间下载,没有的话,可以通过下面的地址下载:

http://download.csdn.net/detail/testcs_dn/9513395


编译环境安装配置请参考:Ubuntu 14 server安装Swift运行环境

环境配置好之后,将下载的示例代码解压出来:


主要代码是“main.swift”,内容如下:

/**
 * Copyright IBM Corporation 2016
 *
 * Licensed 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.
 **/

/**
* Creates a simple HTTP server that listens for incoming connections on port 9080.
* For each request receieved, the server simply sends a simple hello world message
* back to the client.
**/

#if os(Linux)
import Glibc
#else
import Darwin
#endif
import Utils
import Foundation

// Create server socket
let address = parseAddress()
let server_sockfd = createSocket(address)
// Listen on socket with queue of 5
listen(server_sockfd, 5)
var active_fd_set = fd_set()
print("Server is listening on port: \(address.port)\n")

// Initialize the set of active sockets
fdSet(server_sockfd, set: &active_fd_set)

let FD_SETSIZE = Int32(1024)

// Generate HTTP response
// Get environment variables
let environmentVars = NSProcessInfo.processInfo().environment
var responseBody = "<html><body>Hello from Swift on Linux!" +
  "<br />" +
  "<br />" +
  "<table border=\"1\">" +
  "<tr><th>Env Variable</th><th>Value</th></tr>"

for (variable, value) in environmentVars {
    responseBody += "<tr><td>\(variable)</td><td>\(value)</td></tr>\n"
}

responseBody += "</table></body></html>"

let httpResponse = "HTTP/1.0 200 OK\n" +
  "Content-Type: text/html\n" +
  "Content-Length: \(responseBody.length) \n\n" +
  responseBody

var clientname = sockaddr_in()
while true {
  // Block until input arrives on one or more active sockets
  var read_fd_set = active_fd_set;
  select(FD_SETSIZE, &read_fd_set, nil, nil, nil)
  // Service all the sockets with input pending
  for i in 0..<FD_SETSIZE {
    if fdIsSet(i,set: &read_fd_set) {
      if i == server_sockfd {
        // Connection request on original socket
        var size = sizeof(sockaddr_in)
        // Accept request and assign socket
        withUnsafeMutablePointers(&clientname, &size) { up1, up2 in
          var client_sockfd = accept(server_sockfd,
            UnsafeMutablePointer(up1),
            UnsafeMutablePointer(up2))
            print("Received connection request from client: " + String(inet_ntoa (clientname.sin_addr)) + ", port " + String(UInt16(clientname.sin_port).bigEndian))
            fdSet(client_sockfd, set: &active_fd_set)
        }
      }
      else {
        // Send HTTP response back to client
        write(i, httpResponse, httpResponse.characters.count)
        // Close client socket
        close(i)
        fdClr(i, set: &active_fd_set)
      }
    }
  }
}
可通过以下命令编译并启动服务:

root@ubuntu:/home/aven/swifttrans# swift build
root@ubuntu:/home/aven/swifttrans# .build/debug/Server
Server is listening on port: 9080

编译时,可能会出现以下错误:

error: unable to invoke subcommand: /usr/bin/swift-build (No such file or directory)

服务启动成功后,我们就可以通过浏览器访问了,结果如下图:




2019-05-04 00:46:23 10km 阅读数 383
  • Ceph 介绍

    能够快速部署 Ceph 分布式存储 部署及维护Ceph 的块存储,对象存储,文件系统存储 Ceph 基础知识的理解以及监控

    24682课时 0分钟 697人学习 臧雪园
    免费试看

如何基于facebook/swift构建一个支持HTTP访问的thrift服务?说来话长。我将用分几篇博客介绍这个问题的解决思路和具体实现。

背景说明

我有一个项目facelog,是基于facebook/swift框架(java)开发的。在实际的项目应用时,需要从浏览器端能调用facelog的接口方法,要实现这个功能,一个笨办法就是专门写一个java web应用,相当于一个二传手,对浏览器需要访问的facelog方法,提供GET/POST调用接口供浏览器调用,现在我们就是这么干的,这么做无疑增加了开发工作量,能不能让浏览器直接调用facelog服务的接口方法呢?
如果能这样实现将好处多多:
不需要java web应用设计作为转发用途的POST/GET接口,减少了开发工作量同时也减少了系统的响应延迟及复杂度。

Node.js方案

facebook/swift是基于thrift的java平台的RPC框架。thrift是一种支持广泛开发语言的RPC框架,自然也是支持javascript访问的。
thrift的官方网站的《Javascript Tutorial》详细介绍了如何用在浏览器上用javascript访问thrift服务。参照这个教程可以就可以构建一个node.js服务,浏览器则通过javascript访问node.js提供的thrift接口,在这个tutor中,前端使用javascript,服务端则是用Node.js实现的。

所以参照上面的教程在浏览器上用javascript访问facelog服务是完全可以实现的。然而仔细评估之后,觉得《Javascript Tutorial》提供的这个方案对于我的facelog项目并不是最佳解决方案,原因嘛,总得来说就是更麻烦,如下:

  1. 开发工作量更大
    《Javascript Tutorial》方案中,后端是一个node.js服务。而facelog是一个java平台的服务。如果采用这个方案,我需要重写一个node.js服务作为代理服务转所有的HTTP请求到facelog(java)。对于拥有100多个接口方法的facelog服务,再重写一个一样的node.js转发服务也是不小的工作量,这同样增加了项目的复杂度和系统响应延迟,后续维护的工作量也相应增加。
  2. 部署运维更复杂
    facelog(java)的部署很简单,系统依赖很简单,只需要java虚拟机就可以在命令行直接运行,如果增加一个node.js服务,就需要多一个node的运行平台。对于项目部署和运维都增加了难度和工作量。

所以对于我来说,理想的方案就是运行一个支持XHR(XML Http Request)访问的facelog(java)服务,它占用一个新的端口号,web端通过javascript用浏览器的XMLHttpRequest对象直接调用这个XHR服务。这样对于facelog来说只是增加一个新的端口号而已,新的XHR服务还是在java平台运行。没有中间商赚差价,web端的系统响应迟延与java client是一样的。

TServlet方案

那么thrift的java框架有没有提供HTTP访问能力呢?答案是有的。
请关注org.apache.thrift.server.TServlet这个类。
下面是TServlet的部分代码

public class TServlet extends HttpServlet {
	private final TProcessor processor;
	private final TProtocolFactory inProtocolFactory;
	private final TProtocolFactory outProtocolFactory;
	private final Collection<Map.Entry<String, String>> customHeaders;

	public TServlet(TProcessor processor, TProtocolFactory inProtocolFactory, TProtocolFactory outProtocolFactory) {
		this.processor = processor;
		this.inProtocolFactory = inProtocolFactory;
		this.outProtocolFactory = outProtocolFactory;
		this.customHeaders = new ArrayList<Map.Entry<String, String>>();
	}

	public TServlet(TProcessor processor, TProtocolFactory protocolFactory) {
		this(processor, protocolFactory, protocolFactory);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		TIOStreamTransport inTransport = null;
		TIOStreamTransport outTransport = null;
		try {
			TIOStreamTransport transport;
			response.setContentType("application/x-thrift");
			if (null != this.customHeaders) {
				for (Map.Entry<String, String> header : this.customHeaders) {
					response.addHeader(header.getKey(), header.getValue());
				}
			}
			ServletInputStream in = request.getInputStream();
			ServletOutputStream out = response.getOutputStream();
			inTransport = transport = new TIOStreamTransport((InputStream) in, (OutputStream) out);
			outTransport = transport;
			TProtocol inProtocol = this.inProtocolFactory.getProtocol((TTransport) inTransport);
			TProtocol outProtocol = this.outProtocolFactory.getProtocol((TTransport) outTransport);
			this.processor.process(inProtocol, outProtocol);
			out.flush();
		} catch (TException te) {
			throw new ServletException((Throwable) te);
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}
}

如果你熟悉thrift,在TServlet类的代码中看到TProcessorTProtocol类就明白,这个类继承自javax.servlet.http.HttpServlet,可以将一个thrift接口服务(TProcessor)封装为一个Servlet。有了Servlet,就可以在所有支持Servlet的web容器(比如tomcat)上运行thrift服务了.

当初看到这个类,我好一阵兴奋,庆幸自己这么容易就找到了答案。但深入了解之后,得出一个令人沮丧的结论,TServlet方案也不是适合我的方案。

  1. TProcessorThriftServiceProcessor
    对,org.apache.thrift.TProcessorcom.facebook.swift.service.ThriftServiceProcessor,前一个是thrift(java)定义的接口,后者则是facebook/swift定义的接口,我的facelog项目基于facebook/swift设计,服务接口封装为ThriftServiceProcessor实例,并不能直接作为参数被TServlet封装为Servlet
  2. 额外的Servlet容器
    就算想办法将ThriftServiceProcessor封装为TProcessor丢进TServlet封装为Servlet,也需要tomcat这样的Servlet容器才能运行。原本facelog只需要一个standalone的jar包就能在JVM上运行,项目部署极简单,现在凭空多了个tomcat,配置运行tomcat对于项目部署运维就增加了很多的工作量,所以tomcat对于我来说太重了。
    那么jetty呢?Jetty 是一个开源的servlet容器,可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行(stand-alone)的Java应用提供网络和web连接。但同样要增加一些依赖包不是么?我对jetty并不熟悉,为了解决问题学习jetty的成本也要考虑进去。风险也不小。

Netty http server

这也不行,那也不行,你到底要闹哪样啊?
不想增加tomcat,甚至不想增加额外的依赖库,只基于facebook/swift实现一个XHR服务,让浏览能直接访问thrift服务接口。
对,这就是我的最理想的方案。
太晚了,写不下去了。
请看我的下一篇博客。

《facebook/swift:构建thrift http server(2)–HttpServerCodec》
《facebook/swift:构建thrift http server(3)–CORS跨域》
《facebook/swift:构建thrift http server(4)–ThriftXHRDecoder,ThriftXHREncoder》

2015-01-09 16:13:48 dasgk 阅读数 0
  • Ceph 介绍

    能够快速部署 Ceph 分布式存储 部署及维护Ceph 的块存储,对象存储,文件系统存储 Ceph 基础知识的理解以及监控

    24682课时 0分钟 697人学习 臧雪园
    免费试看

首先获得swift的源代码,使用git clone https://github.opnestack/swift.git来获得源代码,然后看看其中的启动过程swift-init文件源代码如下

#!/usr/bin/env python
# Copyright (c) 2010-2012 OpenStack Foundation
#
# Licensed 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.

import sys
from optparse import OptionParser

from swift.common.manager import Manager, UnknownCommandError, \
    KILL_WAIT, RUN_DIRAGE = """%prog <server>[.config] [<server>[.config] ...] <command> [options]

Commands:
""" + '\n'.join(["%16s: %s" % x for x in Manager.list_commands()])


def main():
    parser = OptionParser(USAGE)#填入提示纤细,将在parser.print()进行输出
	
	#进行参数的解析,如果是-v  则进行存储
    parser.add_option('-v', '--verbose', action="store_true",
                      default=False, help="display verbose output")
					  
	#将-w 后的参数放在parser.wait对象当中
    parser.add_option('-w', '--no-wait', action="store_false", dest="wait",
                      default=True, help="won't wait for server to start "
                      "before returning")
    #解析 -o后的参数,
    parser.add_option('-o', '--once', action="store_true",
                      default=False, help="only run one pass of daemon")
    # this is a negative option, default is options.daemon = True
	#解析 -n后的参数,放在daemon成员对象当中
    parser.add_option('-n', '--no-daemon', action="store_false", dest="daemon",
                      default=True, help="start server interactively")
	#解析-g 后的参数
    parser.add_option('-g', '--graceful', action="store_true",
                      default=False, help="send SIGHUP to supporting servers")
	#解析-c后的参数,并将该成员对象放在parser.number成员对象当中
    parser.add_option('-c', '--config-num', metavar="N", type="int",
                      dest="number", default=0,
                      help="send command to the Nth server only")
	#解析 -k 后的参数,
    parser.add_option('-k', '--kill-wait', metavar="N", type="int",
                      dest="kill_wait", default=KILL_WAIT,
                      help="wait N seconds for processes to die (default 15)")
	#解析 -r后的参数,放在run_dir成员对象中
    parser.add_option('-r', '--run-dir', type="str",
                      dest="run_dir", default=RUN_DIR,
                      help="alternative directory to store running pid files "
                      "default: %s" % RUN_DIR)
    #进行输入参数解析
    options, args = parser.parse_args()

    if len(args) < 2:
        parser.print_help()
        print 'ERROR: specify server(s) and command'
        return 1

    command = args[-1]#python将数组看成是一个环,-1就是0的前一个,也就是最后一个
    servers = args[:-1]#args去掉最后一个之后的数组

    # this is just a silly swap for me cause I always try to "start main"
    commands = dict(Manager.list_commands()).keys()
    #例如,如果输入是swift-init main start 则command是start    servers 则是['swift-init','main']    
   if command not in commands and servers[0] in commands:
        servers.append(command)
        command = servers.pop(0)
我们一步一步的看,假如输入的用户命令是swift-init   main start

那么。我们可以得到

command=start#也即输入的最后一个参数start

而servers=args[:-1]则是args去掉最后一个也即

servers=swift-init main

然后继续分析代码

 commands = dict(Manager.list_commands()).keys()
Manager.list_commands函数在swift/swift/common/manager.py文件当中定义的,
 #在@classname函数中的不使用self而是cls,静态函数使用@staticmethod声明的,可以不带有参数
    def list_commands(cls):
        #返回一系列可以作为命令的函数的字符串,三个双引号,表示三个双引号之间的内容都是一个
        """Get all publicly accessible commands 

        :returns: a list of string tuples (cmd, help), the method names who are
                  decorated as commands
        """
        get_method = lambda cmd: getattr(cls, cmd)#lambda匿名函数,定义了一个变量get_method,参数是cmd,直接调用getattr
        
        return sorted([(x.replace('_', '-'), get_method(x).__doc__.strip())
                       #遍历Manager对象的成员,如果成员又属性'publicly_accessible'
                       #则返回该成员,如果没有,则返回False,对于符合条件的成员则获得一个键值对,一个是名称如"start"一个是描述
                       for x in dir(cls) if
                       getattr(get_method(x), 'publicly_accessible', False)])#

需要注意的是list_commands是一个@clasmethod也即类函数,可以直接使用类来访问.

接下来继续分析代码,一下这段代码的含义是用户输入的最后一个参数不在commands当中,但是第一个却在commands当中,那么我们进行替换,第一个参数设置成command,而最后一个则是服务,避免错误的命令,例如 swift-init main start 是可行的,但是start  swift-init main也是对的!!!

if command not in commands and servers[0] in commands:
        servers.append(command)
        command = servers.pop(0)
继续代码
 manager = Manager(servers, run_dir=options.run_dir)#如上面的输入有效参数是:main,依次加载主要服务

这段代码主要作用是加载服务,如果用户输入的是swift-init  main start ,那么command则是start   servers 则是swift-init main,现在看下Manager的构造函数

 def __init__(self, servers, run_dir=RUN_DIR):
        self.server_names = set()#Manager的server_names初始化为一个集合,我们可以认为servers里面是swift-init main,也即有效参数是main
        for server in servers:
            if server == 'all':
                self.server_names.update(ALL_SERVERS)
            elif server == 'main':
                self.server_names.update(MAIN_SERVERS)  #server_names更新成为  MAIN_SERVERS = ['proxy-server', 'account-server', 'container-server', 'object-server']
            elif server == 'rest':
                self.server_names.update(REST_SERVERS)
            elif '*' in server:
                # convert glob to regex
                self.server_names.update([
                    s for s in ALL_SERVERS if
                    re.match(server.replace('*', '.*'), s)])
            else:
                self.server_names.add(server)

        self.servers = set()#Manager的servers成员初始化成为一个集合
        for name in self.server_names:
            self.servers.add(Server(name, run_dir))#依次添加服务

至此,我们的准备工作完成接下来就是运行命令了...

2016-09-16 10:43:19 yu_xiao_xiao 阅读数 0
  • Ceph 介绍

    能够快速部署 Ceph 分布式存储 部署及维护Ceph 的块存储,对象存储,文件系统存储 Ceph 基础知识的理解以及监控

    24682课时 0分钟 697人学习 臧雪园
    免费试看

Swift 是苹果遵循 Apache 开源授权协议开源的一门编程语言

Swift 3 源代码不兼容旧版本,主要是因为 SE-0005 和 SE-0006 的改进,这些改进不仅影响 Standard Library APIs 命名,还会完全改变 Objective-C APIs (特别是 Cocoa ) 导入到 Swift 的方式。

为了帮助用户迁移到 Swift 3,Xcode 8.0 包含了一个代码迁移工具,可以自动处理大量必需的源变化。

Swift 3.0是一个主要的语言版本。它不是源兼容与2.2和2.3。它包含了以下的语言变化,经历了迅速的演变过程:

se-0002:去除局部函数声明的语法

se-0003:从功能参数去除VaR

se-0004:去除++和--运算符

se-0005:更好的翻译成Objective-C API迅速

se-0006:应用API指南标准库

se-0007:拆下有条件和递增器回路C

se-0008:添加序列的自选一个懒惰的flatmap

se-0016:添加初始化int、uint转换从unsafepointer和unsafemutablepointer

se-0017:改变托管使用unsafepointer

se-0019:快速测试

se-0023:API设计指南

se-0025:作用域的访问级别

se-0029:从功能应用程序中删除元组进行内隐行为

se-0031型装饰调整输入的声明:

se-0032:先添加(如:)的方法sequencetype

se-0033:进口Objective-C常数Swift Types

se-0034:消除线控制语句调试标识符

se-0035:限制输入捕捉到“noescape语境

se-0036:需要枚举实例成员实现点前缀

se-0037:澄清意见与运营商之间的相互作用

se-0038:包管理器支持C语言的目标

se-0039现代化操场的文字:

se-0040:用冒号代替等号的属性参数

se-0043:“多模式”标签声明变量

se-0044:进口成员

se-0046:建立一致的标签的行为在所有参数包括第一标签

se-0047:违约非void函数所以他们警告在未使用的结果

se-0048:泛型类型别名

se-0049:移动@ noescape和@ autoclosure是类型属性

se-0052:改变iteratortype后无保障

se-0053:删除显式使用让功能参数

se-0054:废除implicitlyunwrappedoptional型

se-0055:使不安全的指针为空性的显式使用可选

se-0057:进口Objective-C轻质仿制药

se-0059:更新API命名准则和重写设置相应的API

se-0060:执行命令默认参数

se-0061:添加通用的结果和错误处理autoreleasepool()

se-0062:引用Objective-C关键路径

se-0063:swiftpm系统模块搜索路径

se-0064:引用属性getter和setter Objective-C选择器

se-0065:一种新的收藏和指数模型

se-0066:规范函数类型参数语法需要括号

se-0067:增强浮点协议

se-0069:易变性和基础值类型

se-0070:使可选的要求objective-c-only

se-0071:允许(大多数)成员引用关键词

se-0072:完全消除隐桥接转换迅速

se-0076:添加重写以unsafepointer源无损对unsafemutablepointer方法复制

se-0077:改进算子的声明

se-0081:将WHERE子句结束宣言

se-0085:包管理器命令名称

se-0086:滴NS前缀在急速的基础

se-0088:迅速3命名约定libdispatch现代化

se-0089:重命名字符串。init (_:T)

se-0091:提高协议的操作要求

se-0092:协议typealiases和协议扩展

se-0093:添加一个公共基础属性切片

se-0094:添加序列(第一:下一个:)和序列(状态:下一个:)的程序

se-0095:替代协议< P1,P2和P1和P2 >语法语法

se-0096:转换dynamictype从物业运营商

se-0099:重组条件条款

se-0101:重构sizeof和相关的功能到一个统一的memorylayout结构

se-0102:把“只能进不能退的属性介绍空不型

se-0103:使非逃避关闭默认

se-0106:别名为OSX平台配置测试添加MacOS

se-0107:unsaferawpointer API

se-0109:除去布尔协议

se-0111:删除函数参数的标签类型系统的意义

se-0112:改进nserror桥接

se-0113:以浮点加积分取整函数

se-0114:更新缓冲区的“价值”称为“头”的名字

se-0115:重命名文字语法协议

se-0116:引进Objective-C ID作为迅速任何类型

se-0117:允许区分公共通道和公共overridability

se-0118:关闭参数名称和标签

se-0120:修改分区方法签名

se-0121:删除可选的比较运算符

se-0124:Int.init(标识符)和uint. init(标识符)应该有一个位模式:标签

se-0125:删除nonobjectivecbase和isuniquelyreferenced

se-0127:清理程序指针和缓冲区的程序

se-0128:改变failable unicodescalar初始化failable

se-0129:包管理器测试的命名约定

se-0130:替换重复string.init字符和unicodescalar形式

se-0131 anyhashable:添加到标准库

se-0133:重命名为joined() flatten()

se-0134:重命名两UTF8字符串相关的性质

se-0135:通过SWIFT版本区分包管理器支持

se-0136:值的内存布局

se-0137:避免锁定在传统的协议设计



2016-03-11 11:23:41 androidwd 阅读数 3812
  • Ceph 介绍

    能够快速部署 Ceph 分布式存储 部署及维护Ceph 的块存储,对象存储,文件系统存储 Ceph 基础知识的理解以及监控

    24682课时 0分钟 697人学习 臧雪园
    免费试看

1.    代码引入

<dependency>

              <groupId>org.pacesys</groupId>

              <artifactId>openstack4j</artifactId>

              <version>2.0.9</version>

              <classifier>withdeps</classifier>

</dependency>

2.    授权

Eg:

 

              OSClient os =OSFactory.builder()

                            .endpoint("http://192.168.137.140:5000/v2.0")

                            .credentials("username","userpassword").tenantName("tenantName")

                            .authenticate();

3.    Account账户

一个账户也被称为一个project工程或者一个tenant租户。一个账户给出了容器和对象存在的安全范围。由于账户角色的愿意,与它相关的管理任务并不多。

3.1          获取账户详情

eg:

SwiftAccount account =os.objectStorage().account().get();

3.2          元数据metadata

3.2.1     创建或者更新一个账户的元数据:

boolean successful =os.objectStorage().account().updateMetadata(myMetadataMap);

3.2.2     删除一个账户的元数据:

boolean successful =os.objectStorage().account().deleteMetadata(myMetadataMap);

 

4.    Containers容器

一个容器本章上就是一个存放对象的桶。

Containers can have access security assigned tothem, published against a CDN or be shared publicly.

4.1          容器的查询

列出当前账户的所有容器

List<? extendsSwiftContainer> containers = os.objectStorage().containers().list();

使用更进一步的条件查询

List<? extendsSwiftContainer> containers = os.objectStorage()

                                             .containers()

                                             .list(ContainerListOptions.create()

                                                      .startsWith("J")

                                                     .limit(100)

                                                     // ...

                                              );

4.2          创建容器

// Simple

os.objectStorage().containers().create("myContainerName");

      

// Full control

os.objectStorage().containers().create("myContainer",CreateUpdateContainerOptions.create()

                                                        .accessAnybodyRead()

                                                        .accessWrite(acl)

                                                        .metadata(myMeta)

                                                         //...

                                                      ); #### Updating a Container

更新容器信息与fullcontrol创建容器十分类似。唯一的不同就在于调用方法名称。简短示例:

os.objectStorage().containers().update("myContainer",CreateUpdateContainerOptions);

 

4.3          删除容器

注意:为了成功删除容器,必须在删除之前将他清空。这不是本代码的策略,而是openstack的限制就是如此。

os.objectStorage().containers().delete("myContainer");

 

4.4          创建伪目录

此功能可能由于你部署方式的配置不同而导致不支持。像Rackspace这样的供应商是开箱即支持的。

os.objectStorage().containers().createPath(containerName,"/my/nested/path");

 

4.5          元数据

读取

Map<String,String> md = os.objectStorage().containers().getMetadata(containerName);

创建及更新

boolean successful =os.objectStorage().containers().updateMetadata(containerName, myMetadataMap);

删除元数据

boolean successful =os.objectStorage().containers().deleteMetadata(containerName, myMetadataMap);

 

 

5.    Objects对象

对象就是被上传的文件,证明或者伪目录。对象是与容器相关联的。

5.1          查询

列出一个容器的所有对象

List<? extendsSwiftObject> objs = os.objectStorage().objects().list(containerName);

使用更进一步的条件查询

List<? extendsSwiftObject> objs =os.objectStorage().objects().list(ObjectListOptions.create()

                                       .startsWith("J")

                                       .path("/art/digital")

                                        // ...

                                     );

5.2          创建对象

简单的

String etag =os.objectStorage().objects().put(containerName, objectName,Payloads.create(someFile));

高级的

String etag =os.objectStorage().objects().put(containerName, objectName,

                                              Payloads.create(someFile),

                                              ObjectPutOptions.create()

                                                  .path("/some/path")

                                                 .metadata(md)

                                                 // ...

                                              );

5.3          删除对象

os.objectStorage().objects().delete(containerName,objectName);

5.4          复制对象

String etag =os.objectStorage().objects().copy(ObjectLocation.create(srcContainer,srcObject)

                                               ObjectLocation.create(destContainer, destObject)

                                               );

5.5          元数据

 

获取

Map<String,String> md = os.objectStorage().objects().getMetadata(containerName,objectName);

创建和更新

boolean successful =os.objectStorage().objects().updateMetadata(ObjectLocation.create(containerName,objectName), myMetadataMap);