问题:

使用ionic 2框架开发的app,在使用geolocation插件时,弹出了would like to use your current location的提示。

解决方法:

Geolocation.getCurrentPosition().
then((result: Geoposition) => {
    this.geoPosition = result;
}).
catch((error: any) => {
    console.error(error);
});

Geolocation.watchPosition().
subscribe((result: Geoposition) => {
    this.geoPosition = result;
});
初始化添加到
platform.ready().then(()=> {
});
里。
即,必须要在platform的ready之后。

You probably already know about HTML5‘s <input type="number">. Which if supported by a browser displays a form input optimized for inputting numbers. Whether that means an up/down spinner or an optimized keyboard.

However iOS’ standard behavior for the number input isn’t that ideal. By default iOS will display a standard keyboard slightly modified with a row of numbers at the  top. This isn’t ideal as you don’t need the alphabetic keys and iOS already has a full numeric keypad it could use for the input instead. For reference, other mobile OS such as Android already display their numeric keypad when focusing a number input.

A html5doctor article article went over this, pointed out a trick by Chris Coyier using <input type="text" pattern="[0-9]*"> in which the pattern forces iOS to use it’s numeric keypad, and also mentioned HTML5’s inputmode.

The unfortunate issue with Chris’ technique as-is is the number input is no longer a number input. And the practice of depending on raw string matches to specific regexps in pattern="" to trigger UI changes is non-standard. So while the trick nicely displays a numeric keypad on iOS the input no longer has the spinner interface on desktop browsers and other mobile devices such as Android no longer use their numeric keyboards.

Wondering if this technique could be applied in a meaningful way to a number input without ruining the experience for users with other devices I started experimenting and came up with another technique.

<input type="number" min="0" inputmode="numeric" pattern="[0-9]*" 
title="Non-negative integral number">

I found out that the technique of adding pattern="[0-9]*" to an input to trigger the keypad in iOS works even when the input is type="number" so both type="number" and pattern are used. inputmode="numeric" was added for forward compatibility as unlike pattern="[0-9]*" is is the standard way to declare that a numeric mode of user input should be used for a form field.

I also realized that the use of pattern triggers the browser’s native form validation. Which in the case of browsers – like Firefox – which have implemented form validation but not type="number" results in the browser displaying a cryptic “Please match the requested format.” message when the user attempts to submit the form and the number input contains some non-numeric characters. So a title was added which is the standard way to note what type of input is expected within the form field and causes that text to be used inside the error message to describe what the format is.

pattern is ignored by most browsers that implement type="number" but is used by browsers that implement form validation but not the number input type such as Firefox. The pattern [0-9]* which is the only one that iOS will accept to trigger the keypad only permits the input of non-negative integral numbers. So I added min="0" to force browsers implementing type="number" from accepting negative numbers which other browsers would reject.

This technique works in all browsers; Displaying numeric keypads on iOS as well as Android and any other mobile device that’s implemented type="number" or inputmode="numeric" handling. Displaying the numeric spinner on browsers where it’s implemented such as Chrome and Opera. And displaying user friendly form validation on browsers like Firefox that have validation but no number input.

If you have an iOS device you can try out the demo which is depicted by figure 1 and figure 2.

This technique technically does not validate. As the spec defines inputmode and pattern as attributes on textual inputs but not on type="number". However the semantic meaning of these attributes is known and matches the semantic meaning of type="number". So while it is technically invalid the technique is safe to use and the better user experience is worth any error messages in a validator.

         

 

link: http://danielfriesen.name/blog/2013/09/19/input-type-number-and-ios-numeric-keypad/

在开发cordova插件时,有些参数是中文字符串的,但是默认创建的工程里传递中文时会出现乱码。
解决方法是添加如下head头即可

<meta http-equiv=“Content-Type” content=“text/html; charset=utf-8” />

 

文章目录

由于某种原因ssh的端口号由原来的22调整为92573,因此在使用git仓库时,地址也相应进行变更,详细说明如下:

1、克隆仓库

由原来的克隆命令

git clone git@192.168.4.46:test.git

变更为

git clone ssh://git@192.168.4.46:92573/test.git

2、修改仓库url地址

如果之前已经克隆过仓库,则只需修改url地址即可。
编辑.git/config文件
将url地址由git@192.168.4.46:test.git 修改为 ssh://git@192.168.4.46:92573/test.git
保存文件
git pull 同步即可。

3、改动的地方

增加了ssh://
增加了端口号
把用户名前面的冒号改成了斜杠(/)

因/synchrony-proxy/resources/js/vendor/sockjs.min.js等502 Bad Gateway加载不出来,导致无法使用编辑页的解决方法:关闭掉Synchrony proxy即可。

具体方法:
1. 编辑<home-directory>/confluence.cfg.xml

    <property name="synchrony.proxy.enabled">true</property>

修改为

    <property name="synchrony.proxy.enabled">false</property> 

2. 重启Confluence。

文章目录

背景

当今互联网,数据呈现爆炸式增长,社交网络、移动通信、网络视频、电子商务等各种应用往往能产生亿级甚至十亿、百亿级的海量小文件。由于在元数据管理、访问性能、存储效率等方面面临巨大的挑战,海量小文件问题成为了业界公认的难题。

业界的一些知名互联网公司,也对海量小文件提出了解决方案,例如:著名的社交网站Facebook,存储了超过600亿张图片,专门推出了Haystack系统,针对海量小图片进行定制优化的存储。

白山云存储CWN-X针对小文件问题,也推出独有的解决方案,我们称之为Haystack_plus。该系统提供高性能数据读写、数据快速恢复、定期重组合并等功能。

Facebook的Haystack

Facebook的Haystack对小文件的解决办法是合并小文件。将小文件数据依次追加到数据文件中,并且生成索引文件,通过索引来查找小文件在数据文件中的offset和size,对文件进行读取。

Haystack的数据文件部分

Haystack的数据文件,将每个小文件封装成一个needle,包含文件的key、size、data等数据信息。所有小文件按写入的先后顺序追加到数据文件中。

Haystack的索引文件部分

Haystack的索引文件保存每个needle的key,以及该needle在数据文件中的offset、size等信息。程序启动时会将索引加载到内存中,在内存中通过查找索引,来定位在数据文件中的偏移量和大小。

Haystack面临的问题

Facebook的Haystack特点是将文件的完整key都加载到内存中,进行文件定位。机器内存足够大的情况下,Facebook完整的8字节key可以全部加载到内存中。

但是现实环境下有两个主要问题:

  1. 存储服务器内存不会太大,一般为32G至64G;
  2. 小文件对应的key大小难控制,一般选择文件内容的MD5或SHA1作为该文件的key。

场景举例

  • 一台存储服务器有12块4T磁盘,内存为32GB左右。
  • 服务器上现需存储大小约为4K的头像、缩略图等文件,约为10亿个。
  • 文件的key使用MD5,加上offset和size字段,平均一个小文件对应的索引信息占用28字节。
  • 在这种情况下,索引占用内存接近30GB,磁盘仅占用4TB。内存消耗近100%,磁盘消耗只有8%。

所以索引优化是一个必须要解决的问题。

Haystack_plus

Haystack_plus的核心也由数据文件和索引文件组成。

1. Haystack_plus的数据文件

与Facebook的Haystack类似,Haystack_plus将多个小文件写入到一个数据文件中,每个needle保存key、size、data等信息。

2. Haystack_plus的索引文件

索引是我们主要优化的方向:

  • 索引文件只保存key的前四字节,而非完整的key;
  • 索引文件中的offset和size字段,通过512字节对齐,节省1个字节;并根据整个Haystack_plus数据文件实际大小计算offset和size使用的字节数。

3. Haystack_plus的不同之处

数据文件中的needle按照key的字母顺序存放。

由于索引文件的key,只保存前四字节,如果小文件key的前四字节相同,不顺序存放,就无法找到key的具体位置。可能出现如下情况:

例如:用户读取的文件key是0x ab cd ef ac ee,但由于索引文件中的key只保存前四字节,只能匹配0x ab cd ef ac这个前缀,此时无法定位到具体要读取的offset。

我们可以通过needle顺序存放,来解决这个问题:

例如:用户读取文件的key是0x ab cd ef ac bb,匹配到0x ab cd ef ac这个前缀,此时offset指向0x ab cd ef ac aa这个needle,第一次匹配未命中。

通过存放在needle header中的size,我们可以定位0x ab cd ef ac bb位置,匹配到正确needle,并将数据读取给用户。

4. 索引搜索流程为

5. 请求不存在的文件

问题:我们应用折半查找算法在内存查找key,时间复杂度为O(log(n)),其中n为needle数目。索引前缀相同时,需要在数据文件中继续查找。此时访问的文件不存在时,容易造成多次IO查找。

解决方法:在内存中,将存在的文件映射到bloom filter中。此时只需要通过快速搜索,就可以排除不存在的文件。

时间复杂度为O(k),k为一个元素需要的bit位数。当k为9.6时,误报率为1%,如果k再增加4.8,误报率将降低为0.1%。

6. 前缀压缩,效果如何

Haystack_plus与Facebook Haystack内存消耗的对比,场景举例,文件(如:头像、缩略图等)大小4K,key为MD5:

内存消耗对比

Key

offset

size

Haystack

全量key,16字节

8字节

4字节

Haystack_plus

4字节

4字节

1字节

注:Haystack的needle为追加写入,因此offset和size大小固定。Haystack_plus的key使用其前4字节,offset根据Haystack_plus数据文件的地址空间计算字节数,并按512字节对齐;size根据实际文件的大小计算字节数,并按512对齐。

从上图可以看出在文件数量为10亿的情况下,使用Facabook的Haystack消耗的内存超过26G,使用Haystack_plus仅消耗9G多内存,内存使用降低了2/3。

7.索引优化根本就停不下来

10亿个4K小文件,消耗内存超过9G。Key占用4字节,Offset占用4字节,还需要再小一些。

索引分层

根据文件key的前缀,进行分层,相同的前缀为一层。

分层的好处

减少key的字节数

通过分层,只保存一份重复的前缀,节省key的字节数。

减少offset的字节数

优化前的offset,偏移范围为整个Haystack_plus的数据文件的地址空间。

优化后,只需在数据文件中的层内进行偏移,根据最大的层地址空间可以计算所需字节数。

分层后的效果

从上图可以看出,进行分层后,内存消耗从优化前的9G多,降低到4G多,节省了一半的内存消耗。

Haystack_plus整体架构

1. Haystack_plus组织

每台服务器上,我们将所有文件分成多个group,每个group创建一个Haystack_plus。系统对所有的Haystack_plus进行统一管理。

读、写、删除等操作,都会在系统中定位操作某个Haystack_plus,然后通过索引定位具体的needle,进行操作。

2. 索引组织

之前已经介绍过,所有needle顺序存放,索引做前缀压缩,并分层。

3. 文件组成

  • chunk文件:小文件的实际数据被拆分保存在固定数量的chunk数据文件中,默认为12个数据块;
  • needle list文件:保存每个needle的信息(如文件名、offset等);
  • needle index和layer index文件:保存needle list在内存中的索引信息;
  • global version文件:保存版本信息,创建新version时自动将新版本信息追加到该文件中;
  • attribute文件:保存系统的属性信息(如chunk的SHA1等);
  • original filenames:保存所有文件原始文件名。

A、Haystack_plus数据文件被拆分为多个chunk组织,chunk1,chunk2,chunk3……

B、分成多个chunk的好处:

1. 数据损坏时,不影响其它chunk的数据;

2. 数据恢复时,只需恢复损坏的chunk。

C、每个chunk的SHA1值存放在attribute文件中。

4. 版本控制

由于needle在数据文件中按key有序存放,为不影响其顺序,新上传的文件无法加入Haystack_plus,而是首先被保存到hash目录下,再通过定期自动合并方式,将新文件加入到Haystack_plus中。

合并时将从needle_list文件中读取所有needle信息,将删除的needle剔除,并加入新上传的文件,同时重新排序,生成chunk数据文件、索引文件等。

重新合并时将生成一个新版本Haystack_plus。版本名称是所有用户的文件名排序的SHA1值的前4字节。

每半个月系统自动进行一次hash目录检查,查看是否有新文件,并计算下所有文件名集合的SHA1,查看与当前版本号是否相同,不同时说明有新文件上传,系统将重新合并生成新的数据文件。

同时,系统允许在hash目录下超过指定的文件数时,再重新创建新版本,从而减少重新合并次数。

版本的控制记录在global_version文件中,每次创建一个新版本,版本号和对应的crc32将追加到global_version文件(crc32用于查看版本号是否损坏)。

每次生成新版本时,自动通知程序重新载入索引文件、attribute文件等。

5. 数据恢复

用户的文件将保存成三副本存放,因此Haystack_plus也会存放在3台不同的机器上。

恢复场景一

当一个Haystack_plus的文件损坏时,会在副本机器上,查找是否有相同版本的Haystack_plus,如果版本相同,说明文件的内容都是一致,此时只需将要恢复的文件从副本机器下载下来,进行替换。

恢复场景二

如果副本机器没有相同版本的Haystack_plus,但存在更高版本,那此时可以将该版本的整个Haystack_plus从副本机器上拷贝下来,进行替换。

恢复场景三

如果前两种情况都不匹配,那就从另外两台副本机器上,将所有文件都读到本地上的hash目录下,并将未损坏的chunk中保存的文件也提取到hash目录下,用所有文件重新生成新版本的Haystack_plus。

Haystack_plus效果如何

在使用Haystack_plus后一段时间,我们发现小文件的整体性能有显著提高,RPS提升一倍多,机器的IO使用率减少了将近一倍。同时,因为优化了最小存储单元,碎片降低80%。

使用该系统我们可以为用户提供更快速地读写服务,并且节省了集群的资源消耗。

Link: http://www.infoq.com/cn/articles/solution-of-massive-small-files

Nginx的默认配置是不支持的pathinfo的,要支持path_info也很简单。
原配置如下

      location ~ \.php$ {
            root           /data0/wwwroot/default;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /data0/wwwroot/default$fastcgi_script_name;
            include        fastcgi_params;
      }

修改为:

        location ~ \.php(.*)$ {
            root           /data0/wwwroot/default;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param PATH_INFO $fastcgi_path_info;
            fastcgi_param  SCRIPT_FILENAME  /data0/wwwroot/default$fastcgi_script_name;
            include        fastcgi_params;
        }

修改的地方:
1、将location ~ \.php$ 修改为 location ~ \.php(.*)$
2、添加如下两行

    fastcgi_split_path_info ^(.+\.php)(.*)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;

这个pathinfo的问题碰到好几次了,每一次都是thinkPHP框架所致,远离thinkPHP,幸福一生。

文章目录

One of the core components of Mac OS X is launchd, and it turns out it can do some cool things.

I particularly like the idea of using QueueDirectories to monitor and act upon files dropped into a directory, without having to run any extra daemons. The files could be uploaded to S3, transcoded to a different video format, gzipped… anything.

Anyway, I recently fell into the launchd documentation, and came out with this write-up. Let me know if you find it useful.

Overview

The first thing that the Mac OS kernel runs on boot is launchd, which bootstraps the rest of the system by loading and managing various daemons, agents, scripts and other processes. The launchd man page clarifies the difference between a daemon and an agent:

In the launchd lexicon, a “daemon” is, by definition, a system-wide service of which there is one instance for all clients. An “agent” is a service that runs on a per-user basis. Daemons should not attempt to display UI or interact directly with a user’s login session. Any and all work that involves interacting with a user should be done through agents.

Daemons and agents are declared and configured by creating .plist files in various locations of the system:

~/Library/LaunchAgents         Per-user agents provided by the user.
/Library/LaunchAgents          Per-user agents provided by the administrator.
/Library/LaunchDaemons         System-wide daemons provided by the administrator.
/System/Library/LaunchAgents   Per-user agents provided by OS X.
/System/Library/LaunchDaemons  System-wide daemons provided by OS X.

Perhaps best of all, launchd is open source under the Apache License 2.0. You can currently find the latest source code on the Apple Open Source site.

launchd as cron

The Mac OS crontab man page says:

Although cron(8) and crontab(5) are officially supported under Darwin,
their functionality has been absorbed into launchd(8), which provides a
more flexible way of automatically executing commands.

Turns out launchd has a simple StartInterval <integer> property, which starts the job every N seconds. However the true cron-like power lies in StartCalendarInterval:

StartCalendarInterval <dictionary of integers or array of dictionary of integers>

This optional key causes the job to be started every calendar interval as
specified. Missing arguments are considered to be wildcard. The semantics
are much like crontab(5).  Unlike cron which skips job invocations when the
computer is asleep, launchd will start the job the next time the computer
wakes up.  If multiple intervals transpire before the computer is woken,
those events will be coalesced into one event upon wake from sleep.

     Minute <integer>
     The minute on which this job will be run.

     Hour <integer>
     The hour on which this job will be run.

     Day <integer>
     The day on which this job will be run.

     Weekday <integer>
     The weekday on which this job will be run (0 and 7 are Sunday).

     Month <integer>
     The month on which this job will be run.

Lets find the shortest example of this in action:

pda@paulbook ~ > grep -rl StartCalendarInterval \
                   /Library/Launch* /System/Library/Launch* | \
                   xargs wc -l | sort -n | head -n1 | awk '{print $2}' | xargs cat

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>Label</key>
        <string>com.apple.gkreport</string>
        <key>ProgramArguments</key>
        <array>
                <string>/usr/libexec/gkreport</string>
        </array>
        <key>StartCalendarInterval</key>
        <dict>
                <key>Minute</key><integer>52</integer>
                <key>Hour</key><integer>3</integer>
                <key>WeekDay</key><integer>5</integer>
        </dict>
</dict>
</plist>

Better than cron? Apart from better handling of skipped jobs after system wake, it also supports per-job environment variables, which can save writing wrapper scripts around your cron jobs:

EnvironmentVariables <dictionary of strings>

This optional key is used to specify additional environmental variables to
be set before running the job.

So, anything XML is obviously worse than 0 52 3 * 5 /path/to/command, but launchd is packing more features than cron, so it can pull it off.

launchd as a filesystem watcher

Apart from having an awesome daemon/agent manager, Mac OS X also has an excellent Mail Transport Agent called postfix. There’s a good chance your ISP runs the same software to handle millions of emails every day. We’ll be using it as an example of how launchd can start jobs based on filesystem changes.

Because your laptop isn’t, and shouldn’t be, a mail server, you don’t want postfix running all the time. But when messages are injected into it, e.g. by a script shelling out to /usr/sbin/sendmail or /usr/bin/mail, you want them to be delivered straight away.

Here’s how Mac OS X does it (/System/Library/LaunchDaemons/org.postfix.master.plist):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>org.postfix.master</string>
    <key>Program</key>
    <string>/usr/libexec/postfix/master</string>
    <key>ProgramArguments</key>
    <array>
        <string>master</string>
        <string>-e</string>
        <string>60</string>
    </array>
    <key>QueueDirectories</key>
    <array>
        <string>/var/spool/postfix/maildrop</string>
    </array>
    <key>AbandonProcessGroup</key>
    <true/>
</dict>
</plist>

We’ll start with the simple part. ProgramArguments passes -e 60 to postfix, described thusly:

-e exit_time
              Terminate the master process after exit_time seconds.
              Child processes terminate at their convenience.

So postfix is told to exit after running for 60 seconds. The mystery (to me, earlier today, at least) is how it gets started. It could be on a cron-like schedule, but (a) it isn’t, (b) that would suck, and (c) it would result in delayed mail delivery. It turns out the magic lies in QueueDirectory, which I initially overlooked thinking it was a postfix option. The launchd.plist man page says:

WatchPaths <array of strings>
This optional key causes the job to be started if any one of the listed
paths are modified.

QueueDirectories <array of strings>
Much like the WatchPaths option, this key will watch the paths for
modifications. The difference being that the job will only be started if
the path is a directory and the directory is not empty.

The Launchd Wikipedia page actually goes into more detail:

QueueDirectories
Watch a directory for new files. The directory must be empty to begin with,
and must be returned to an empty state before QueueDirectories will launch
its task again.

So launchd can monitor a directory for new files, and then trigger an agent/daemon to consume them. In this case, the postfix sendmail(1) man page tells us that “Postfix sendmail(1) relies on the postdrop(1) command to create a queue file in the maildrop directory”, and the man page for postdrop(1) tells us that /var/spool/postfix/maildrop is the maildrop queue. launchd sees new mail there, fires up postfix, and then stops it after 60 seconds. This might cause deferred mail to stay deferred for quite some time, but again; your laptop isn’t a mail server.

launchd as inetd

Tranditionally the inetd and later xinetd “super-server daemon” were used to listen on various ports (e.g. FTP, telnet, …) and launch daemons on-demand to handle in-bound connection, keeping them out of memory at other times. Sounds like something launchd could do…

Lets create a simple inetd-style server at ~/Library/LaunchAgents/my.greeter.plist:

<plist version="1.0">
<dict>
  <key>Label</key><string>my.greeter</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/bin/ruby</string>
    <string>-e</string>
    <string>puts "Hi #{gets.match(/(\w+)\W*\z/)[1]}, happy #{Time.now.strftime("%A")}!"</string>
  </array>
  <key>inetdCompatibility</key><dict><key>Wait</key><false/></dict>
  <key>Sockets</key>
  <dict>
    <key>Listeners</key>
    <dict>
      <key>SockServiceName</key><string>13117</string>
    </dict>
  </dict>
</dict>
</plist>

Load it up and give it a shot:

pda@paulbook ~ > launchctl load ~/Library/LaunchAgents/my.greeter.plist
pda@paulbook ~ > echo "My name is Paul." | nc localhost 13117
Hi Paul, happy Friday!

launchd as god!

You can use launchd to ensure a process stays alive forever using <key>KeepAlive</key><true/>, or stays alive under the following conditions.

  • SuccessfulExit — the previous run exited successfully (or if false, unsuccessful exit).
  • NetworkState — network (other than localhost) is up (or if false, down).
  • PathState — list of file paths exists (or if false, do not exist).
  • OtherJobEnabled — the other named job is enabled (or if false, disabled).

These can be combined with various other properties, for example:

  • WorkingDirectory
  • EnvironmentVariables
  • Umask
  • ThrottleInterval
  • StartOnMount
  • StandardInPath
  • StandardOutPath
  • StandardErrorPath
  • SoftResourceLimits and HardResourceLimits
  • Nice

More?

There’s some more information at developer.apple.com, and the launchd and launchd.plist man pages are worth reading.

link: http://paul.annesley.cc/2012/09/mac-os-x-launchd-is-cool/

在安装Bundler过程中出现了错误:

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/include/ruby-2.0.0/ruby/ruby.h:24:10: fatal error: 'ruby/config.h' file not found
#include "ruby/config.h"
^
1 error generated.
make: *** [generator.o] Error 1

原因是:
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/include/ruby-2.0.0/ruby目录下缺少config.h文件

解决方法:
拷贝xcode中的该配置文件到/usr/local/include目录下。
命令如下:
sudo cp -rf /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/include/ruby-2.0.0/universal-darwin15/ruby /usr/local/include/

PS: /System/Library 目录是有系统保护,禁止修改的,因此拷贝到/usr/local/include即可。

在mac os x系统编译php时,在configure阶段就报如下错误:

error: Don’t know how to define struct flock on this system, set –enable-opcache=no

解决方法:

sudo cp /opt/mysql/lib/libmysqlclient.* /usr/local/lib/libmysqlclient.*